package com.mc.lp.database.service.handler;

import java.util.ArrayList;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

import com.mc.lp.database.service.handler.event.IEvent;
import com.mc.lp.database.service.handler.exception.EventHandlingException;
import com.mc.lp.service.MicroCampusAbstractService;
import com.mc.lp.shared.service.executor.IExecutorService;


/**
 * event handler service will handle the events and trigger the appropriate listener.
 * @author deepak
 *	IMPORTANT: CURRENTY WE ARE SUPPORTING ONLY ONE HANDLER PER EVENT. IN FUTURE WE WILL SUPPORT MULTIPLE HANDLER PER EVENT.
 *	USER CAN ALSO ATTACH MANY EVENT(CREATE A FAMILY OF EVENT) AT ONCE, ALL EVENTS WILL BE EXECUTED USING EXECTOR FRAMEWORK 
 *	AND ONCE COMPLETED RETURN THE VALUE RESPECTIVELY.
 */
public class SimpleEventExecutor extends MicroCampusAbstractService<SimpleEventExecutor> implements IEventExecutor{
	/**
	 * this list will hold event handler list
	 */
	public ArrayList<EventHandler> eventHandlers;
	/**
	 * this resource will hold executor service, to achieve asynchronous  calls to handlers.
	 */
	public IExecutorService executorService;
	
	/**
	 * 	asynchronously calls handler's method and pass on the execution to call thread instantly to save user response time.
	 * 	IMPORTANT! currently we are not handling any return type from the future service.
	 * 	@param event
	 */
	public void fireEvent(final IEvent event){
		LOG.debug("FireEventTriggered for event :"+event.getEventType());
		EventHandler handler=getHandler(event);
		Callable<EventResponse> callable=handler.getCallable(event);
		executorService.executeTask(new FutureTask<EventResponse>(callable));
		LOG.debug("Handler Found :"+ handler);
		LOG.debug("Fire Event Triggered :"+event.getEventType());
	}
	
	/**
	 * this fire event will work in the same thread and return the response once it gets completed.
	 * @param event
	 * @return
	 * @throws EventHandlingException 
	 */
	public EventResponse fireBlockerEvent(final IEvent event) throws EventHandlingException{
		LOG.debug("FireBlockerEventTriggered for event :"+event.getEventType());
		EventHandler handler=getHandler(event);
		LOG.debug("Handler Found :"+ handler);
		return handler.handleEvent(event);
	}
	
	/**
	 * returns the appropriate handler from the registered handlers.
	 * @param event
	 * @return
	 */
	private EventHandler getHandler(IEvent event){
		for(EventHandler handler:this.eventHandlers){
			if(handler.getEventType().equals(event.getEventType()))
				return handler;
		}
		throw new NullPointerException("No Event handler found");
	}

	public ArrayList<EventHandler> getEventHandlers() {
		return eventHandlers;
	}

	public void setEventHandlers(ArrayList<EventHandler> eventHandlers) {
		this.eventHandlers = eventHandlers;
	}

	public IExecutorService getExecutorService() {
		return executorService;
	}

	public void setExecutorService(IExecutorService executorService) {
		this.executorService = executorService;
	}
}